package com.misc.tunewsreader;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TextView;

import com.markupartist.android.widget.ActionBar;
import com.markupartist.android.widget.ActionBar.AbstractAction;
import com.misc.tunewsreader.TUNewsReaderActivity.OfflineModeAction;

public class ThreadView extends Activity {

	private List<NNTPThreadInfo> threads;
	ProgressDialog load_progress;

	public static final int Menu_post = Menu.FIRST + 1;
	public static MenuItem m_post;
	public static NNTPThreadInfo last_thread = null;
	public static final int Menu_asunread = Menu.FIRST + 1;
	public static final int Menu_asread = Menu.FIRST + 2;
	public ThreadAdapter adapter;
	private ActionBar action;
	private static Thread load_thread;
	private Parcelable state = null;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.threads);

		action = (ActionBar) findViewById(R.id.actionbar);
		// posting and refreshing is only possible in online mode
		if (!NNTPClient.isOfflineMode()) {
			action.addAction(new RefreshAction(this, R.drawable.bar_refresh));
			action.addAction(new PostAction(this, R.drawable.bar_new));
		} else {
			action.addAction(new OfflineModeAction(this, R.drawable.bar_warning));
		}
		action.setDisplayHomeAsUpEnabled(true);
		action.setOnTitleClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				finish();
			}
		});
		// show loading
		action.setTitle(this.getString(R.string.title_loading));
		// set progress indicator
		action.setProgressBarVisibility(View.VISIBLE);

		loadPosts();

	}

	@Override
	protected void onResume() {
		super.onResume();
		// restore listview state
		if (state != null) {
			((ListView) findViewById(R.id.threads))
					.onRestoreInstanceState(state);
		}
	}

	@Override
	protected void onPause() {
		super.onPause();
		// save listview state
		state = ((ListView) findViewById(R.id.threads)).onSaveInstanceState();
	}

	public static class RefreshAction extends AbstractAction {
		private Context mContext;

		public RefreshAction(Context context, int drawable) {
			super(drawable);
			mContext = context;
		}

		@Override
		public void performAction(View view) {
			/*
			 * NNTPGroup group = NNTPClient.getCurrentGroup(); //
			 * NNTPClient.reloadGroup(group); NNTPClient.enterGroup(group);
			 */
			((ThreadView) mContext).refreshThreads(view);
		}
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		// orientation changing while loading thread is not supported
		if (action.getProgressBarVisibility() == View.VISIBLE)
			return;

		onCreate(null);
	}

	public static class PostAction extends AbstractAction {
		private Context mContext;

		public PostAction(Context context, int drawable) {
			super(drawable);
			mContext = context;
		}

		@Override
		public void performAction(View view) {
			final Intent intent = new Intent(mContext, WritePost.class);
			intent.putExtra("newsgroup", NNTPClient.getCurrentGroup().getName());
			((ThreadView) mContext).startActivity(intent);
		}
	}

	public void refreshThreads(View v) {
		// set progress indicator
		action.setProgressBarVisibility(View.VISIBLE);
		Runnable reenter = new Runnable() {

			@Override
			public void run() {
				// NNTPClient.reloadGroup(group);
				NNTPGroup group = NNTPClient.getCurrentGroup();
				NNTPClient.enterGroup(group);
				loadPosts();
			}
		};
		Thread thread = new Thread(null, reenter, "ReEnterGroup");
		thread.start();
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		if (v.getId() == R.id.threads) {
			menu.setHeaderTitle(getApplicationContext().getString(
					R.string.thread_menu_title));
			menu.add(Menu.NONE, Menu_asread, 0, getApplicationContext()
					.getString(R.string.mark_as_read));
			menu.add(Menu.NONE, Menu_asunread, 1, getApplicationContext()
					.getString(R.string.mark_as_unread));
		}
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
				.getMenuInfo();

		NNTPThreadInfo thread = (NNTPThreadInfo) adapter.getItem(info.position);
		List<NNTPPost> replies = NNTPClient.getReplies(thread);

		// save listview state
		state = ((ListView) findViewById(R.id.threads)).onSaveInstanceState();

		switch (item.getItemId()) {

		case Menu_asread:
			/*
			 * Toast.makeText(getApplicationContext(), "Mark as read",
			 * Toast.LENGTH_SHORT).show();
			 */
			thread.invalidate();
			NNTPClient.markPostRead(thread.getThreadId(), true);
			for (int i = 0; i < replies.size(); i++) {
				NNTPClient.markPostRead(replies.get(i).getHeader()
						.getThreadId(), true);
			}
			loadPosts();
			break;

		case Menu_asunread:
			/*
			 * Toast.makeText(getApplicationContext(), "Mark as unread",
			 * Toast.LENGTH_SHORT).show();
			 */
			thread.invalidate();
			NNTPClient.markPostRead(thread.getThreadId(), false);
			for (int i = 0; i < replies.size(); i++) {
				NNTPClient.markPostRead(replies.get(i).getHeader()
						.getThreadId(), false);
			}
			loadPosts();
			break;
		}
		return true;
	}

	void loadPosts() {
		try {
			load_progress = new ProgressDialog(this);
			load_progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			load_progress.setTitle(this.getString(R.string.loading));
			load_progress.setMessage(this
					.getString(R.string.loading_threads_wait));
			load_progress.setIndeterminate(true);
			load_progress.setMax(0);
			load_progress.setProgress(2);
			load_progress.setOnCancelListener(new OnCancelListener() {
				@Override
				public void onCancel(DialogInterface dialog) {
					NNTPClient.stopLoading();
					while (NNTPClient.isLoadingAllPosts()) {
						// do nothing and wait
						Log.d("NNTP", "wait...");
					}
					finish();
				}
			});
		} catch (Exception e) {
		}

		Runnable postLoad = new Runnable() {
			@Override
			public void run() {
				// NNTPClient.setContext(getApplicationContext());
				NNTPClient.loadAllPosts(true, load_progress);
				// NNTPClient.markPostsReadByMsgId(Sync.getReadMessages());
				// close loading dialog
				try {
					load_progress.dismiss();
				} catch (Exception e) {
				}
				// create threads
				runOnUiThread(returnRes);
			}
		};
		load_thread = new Thread(null, postLoad, "LoadPosts");

		// if we have more than 50 new posts, ask the user first
		if (NNTPClient.getNewPostCount() > 50) {
			showDownloadLimitDialog(NNTPClient.getNewPostCount());
		} else {
			load_thread.start();
		}
	}

	private void showDownloadLimitDialog(int count) {
		LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		final View download = inflater.inflate(R.layout.download_ask, null);
		// when selecting download limit edittext or typing in it, automatically
		// selected correct radio button
		download.findViewById(R.id.download_count).setOnFocusChangeListener(
				new OnFocusChangeListener() {
					@Override
					public void onFocusChange(View v, boolean hasFocus) {
						if (hasFocus) {
							((RadioButton) download
									.findViewById(R.id.download_limit))
									.setChecked(true);
						}
					}
				});
		download.findViewById(R.id.download_count).setOnKeyListener(
				new OnKeyListener() {
					@Override
					public boolean onKey(View v, int keyCode, KeyEvent event) {
						((RadioButton) download
								.findViewById(R.id.download_limit))
								.setChecked(true);
						return false;
					}
				});

		Builder download_dlg = new AlertDialog.Builder(this)
				.setView(download)
				.setTitle(NNTPClient.getCurrentGroup().getName())
				.setMessage("There are " + count + " posts in this newsgroup")
				.setPositiveButton(getString(R.string.download),
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int whichButton) {
								if (((RadioButton) download
										.findViewById(R.id.download_all))
										.isChecked())
									NNTPClient.setLoadLimit(-1);
								else {
									int limit = -1;

									limit = Integer.parseInt(((EditText) download
											.findViewById(R.id.download_count))
											.getText().toString());
									Log.d("NNTP", "Load only " + limit
											+ " posts");
									NNTPClient.setLoadLimit(limit);
								}
								load_thread.start();
							}
						})
				.setNegativeButton(getString(R.string.cancel),
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int whichButton) {
								finish();
							}
						}).setCancelable(false);
		download_dlg.show();
	}

	private Runnable returnRes = new Runnable() {
		@Override
		public void run() {
			loadThreads();
			// restore listview state
			if (state != null) {
				((ListView) findViewById(R.id.threads))
						.onRestoreInstanceState(state);
			}
			action.setProgressBarVisibility(View.GONE);
		}
	};

	private void loadThreads() {
		List<NNTPThreadInfo> all_threads = NNTPClient.getAllThreads();
		threads = new ArrayList<NNTPThreadInfo>();

		// check if we should hide read threads
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(getApplicationContext());
		boolean hide_read = prefs.getBoolean("pref_hide_read", false);

		// get unread count and hide read threads if this option is set
		int total_unread = 0;
		for (int i = 0; i < all_threads.size(); i++) {
			total_unread += all_threads.get(i).getUnread();
			if (!hide_read || (hide_read && all_threads.get(i).getUnread() > 0)) {
				threads.add(all_threads.get(i));
			}
		}

		ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
		actionBar.setTitle(NNTPClient.getCurrentGroup().getName() + " ("
				+ total_unread + " "
				+ getApplicationContext().getString(R.string.unread) + ")");

		ListView group_list = (ListView) findViewById(R.id.threads);
		adapter = new ThreadAdapter(this, R.layout.thread_title, threads);
		group_list.setAdapter(adapter);
		group_list.setOnItemClickListener(threadClickListener);
		registerForContextMenu(group_list);
	}

	private NNTPThreadInfo getThreadFromView(View view) {
		if (view == null)
			return null;

		LinearLayout view_parent = (LinearLayout) view;
		TextView thread_id = (TextView) view_parent.findViewById(R.id.threadid);
		if (thread_id == null)
			return null;

		long t_number = Long.parseLong(thread_id.getText().toString().trim());
		for (int i = 0; i < threads.size(); i++) {
			if (threads.get(i).getThreadId() == t_number) {
				return threads.get(i);
			}
		}
		return null;
	}

	OnItemClickListener threadClickListener = new OnItemClickListener() {

		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,
				long id) {
			threadClick(view);
		}

	};

	public void threadClick(View view) {
		NNTPThreadInfo thread = getThreadFromView(view);
		if (thread == null)
			return;

		last_thread = thread;
		final Intent intent = new Intent(getApplicationContext(),
				PostHierarchy.class);

		intent.putExtra("ThreadId", thread.getThreadId());
		startActivityForResult(intent, 0);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (last_thread != null)
			last_thread.invalidate();
		loadThreads();

		super.onActivityResult(requestCode, resultCode, data);
	}

}
